package com.xyz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyz.entity.LoginLog;
import com.xyz.entity.OperationLog;
import com.xyz.entity.User;
import com.xyz.entity.dto.LogLoginDTO;
import com.xyz.entity.dto.LogOperationDTO;
import com.xyz.entity.request.*;
import com.xyz.entity.response.LoginResponse;
import com.xyz.entity.vo.ListUserVO;
import com.xyz.exception.IllegalUsernameOrPasswordException;
import com.xyz.exception.UserNotExistException;
import com.xyz.service.ILoginLogService;
import com.xyz.service.IOperationLogService;
import com.xyz.service.IUserService;
import com.xyz.service.SystemService;
import com.xyz.utils.EncryptSha256Util;
import com.xyz.utils.JwtUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author 夏永泽
 * @date 2022/4/1
 */
@Service
public class SystemServiceImpl implements SystemService {
    private final IUserService userService;
    private final ILoginLogService loginLogService;
    private final IOperationLogService operationLogService;

    public SystemServiceImpl(IUserService userService, ILoginLogService loginLogService, IOperationLogService operationLogService) {
        this.userService = userService;
        this.loginLogService = loginLogService;
        this.operationLogService = operationLogService;
    }

    @Override
    public LoginResponse login(LoginRequest request) {
        // 查询用户是否存在
        User user = this.userService.lambdaQuery().select(User::getSalt).eq(User::getIdNumber, request.getIdNumber()).one();
        if (Objects.isNull(user)) {
            throw new UserNotExistException();
        }
        // 加密密码后和数据库比对密码
        String salt = user.getSalt();
        String password = request.getPassword() + salt;
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().select(User::getIdNumber, User::getName, User::getRole, User::getPhoneNumber).eq(User::getIdNumber, request.getIdNumber()).eq(User::getPassword, EncryptSha256Util.getSha256Str(password));
        User one = this.userService.getOne(wrapper);
        if (one != null) {
            String token = JwtUtils.getToken(one.getName(), one.getRole(), one.getIdNumber());
            LoginResponse loginResponse = new LoginResponse();
            BeanUtils.copyProperties(one, loginResponse);
            return loginResponse.setToken(token).setGender(this.getGender(one.getIdNumber())).setBirthday(this.getBirthday(one.getIdNumber()));
        } else {
            throw new IllegalUsernameOrPasswordException();
        }
    }

    @Override
    public Page<ListUserVO> listUsers(Integer page, Integer limit) {
        // 查询用户列表
        Page<User> page1 = this.userService.lambdaQuery().select(User::getId, User::getName, User::getRole, User::getIdNumber, User::getPhoneNumber).page(new Page<>(page, limit));
        // 转换用户列表格式
        List<ListUserVO> collect = page1.getRecords().stream().map(o -> {
            ListUserVO listUserVO = new ListUserVO();
            BeanUtils.copyProperties(o, listUserVO);
            listUserVO.setBirthday(this.getBirthday(o.getIdNumber()));
            listUserVO.setGender(this.getGender(o.getIdNumber()));
            return listUserVO;
        }).collect(Collectors.toList());
        // 分页返回
        Page<ListUserVO> listUserVOPage = new Page<>();
        BeanUtils.copyProperties(page1, listUserVOPage);
        return listUserVOPage.setRecords(collect);
    }

    @Override
    public ListUserVO getUser(String idNumber) {
        // 查询用户是否存在
        User one = this.userService.lambdaQuery().select(User::getId, User::getName, User::getRole, User::getIdNumber, User::getPhoneNumber).eq(User::getIdNumber, idNumber).one();
        if (Objects.isNull(one)) {
            return null;
        }
        // 如果存在返回查询到的用户
        ListUserVO listUserVO = new ListUserVO();
        BeanUtils.copyProperties(one, listUserVO);
        listUserVO.setBirthday(this.getBirthday(one.getIdNumber()));
        listUserVO.setGender(this.getGender(one.getIdNumber()));
        return listUserVO;
    }

    @Override
    public void updateUser(UpdateUserRequest request) {
        User one = this.userService.lambdaQuery().select(User::getId).eq(User::getIdNumber, request.getIdNumber()).one();
        if (Objects.isNull(one)) {
            throw new UserNotExistException();
        }
        // 参数校验,如果必要参数未输入,则抛出参数异常
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        if (Objects.isNull(request.getRole()) && Objects.isNull(request.getPhoneNumber())) {
            throw new IllegalArgumentException();
        }
        // 传入的手机号不为空则修改手机号
        if (StringUtils.isNotEmpty(request.getPhoneNumber())) {
            wrapper.set(User::getPhoneNumber, request.getPhoneNumber());
        }
        // 传入的角色不为空则修改角色
        if (Objects.nonNull(request.getRole())) {
            wrapper.set(User::getRole, request.getRole());
        }
        wrapper.eq(User::getIdNumber, request.getIdNumber());
        // 执行
        this.userService.update(wrapper);
    }

    @Override
    public void addUser(AddUserRequest request) {
        String salt = EncryptSha256Util.getSha256Str(UUID.randomUUID().toString());
        User user = new User();
        BeanUtils.copyProperties(request, user);
        user.setSalt(salt);
        user.setPassword(EncryptSha256Util.getSha256Str(request.getPassword() + salt));
        this.userService.save(user);
    }

    @Override
    public void deleteUser(Long id) {
        // delete from user where id = #{id}
        this.userService.removeById(id);
    }

    @Override
    public void changePassword(ChangePasswordRequest request) {
        User user = this.userService.lambdaQuery().select(User::getSalt).eq(User::getIdNumber, request.getIdNumber()).one();
        String salt = user.getSalt();
        String password = request.getOriginalPassword() + salt;
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().select(User::getId).eq(User::getIdNumber, request.getIdNumber()).eq(User::getPassword, EncryptSha256Util.getSha256Str(password));
        User one = this.userService.getOne(wrapper);
        if (null != one) {
            String newPassword = request.getNewPassword() + salt;
            this.userService.lambdaUpdate().set(User::getPassword, EncryptSha256Util.getSha256Str(newPassword)).update();
        } else {
            throw new IllegalUsernameOrPasswordException();
        }
    }

    @Override
    public void logLogin(LogLoginDTO dto) {
        loginLogService.save(new LoginLog(dto.getIdNumber()));
    }

    @Override
    public void logOperation(LogOperationDTO dto) {
        OperationLog operationLog = new OperationLog().setOperation(dto.getOperation()).setIdNumber(dto.getIdNumber());
        this.operationLogService.save(operationLog);
    }


    private Date getBirthday(String idNumber) {
        String year = idNumber.substring(6, 10);
        String month = idNumber.substring(10, 12);
        String day = idNumber.substring(12, 14);
        String birthday = year + "-" + month + "-" + day;
        DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        Date date;
        try {
            date = fmt.parse(birthday);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getGender(String idNumber) {
        int i = Integer.parseInt(idNumber.substring(16, 17));

        switch (i % 2) {
            case 1:
                return "男";
            case 2:
                return "女";
            default:
                return "未知";
        }
    }
}
